#pragma once

#include "Source.h"
#include "Sink.h"
#include "OnlineStatistic.h"

// Interface for classes that process input values, run them trhough a statistic and output values.
// This guys could be asynchronous read/write/compute operations for maximum throughput.
template<class TIn, class TOut> class IProcessor {
	public:
        virtual ~IProcessor() {}
		virtual void Run(ISource<TIn>* pSource, IOnlineStatistic<TIn, TOut>* pStatistic, ISink<TOut>* pSink) = 0;
};

// Simple processor that takes a source, runs each value through a statistic and sends the updated statistic to the sink.
template<class TIn, class TOut> class SimpleProcessor : public IProcessor<TIn, TOut> {
	public:
		virtual void Run(ISource<TIn>* pSource, IOnlineStatistic<TIn, TOut>* pStatistic, ISink<TOut>* pSink);
};


// *** *** TEMPLATE IMPLEMENTATIONS *** *** //

template<class TIn, class TOut> void SimpleProcessor<TIn, TOut>::Run(ISource<TIn>* pSource, IOnlineStatistic<TIn, TOut>* pStatistic, ISink<TOut>* pSink) {
	if(pSource == NULL)
		throw "Null pSource pointer.";
	while(pSource->HasValues()) {
		TIn input = pSource->Next();
		TOut statValue;
		if(pStatistic != NULL) {  // Allow straight chaining of in->out if NULL
			pStatistic->RecordInput(input);
			if(pStatistic->HasValue())  // Else leave same value
				statValue = pStatistic->GetCurrentStatistic();
		}
		else
			statValue = input;
		if(pSink != NULL)  // Allow discarding of values if NULL
			pSink->Process(statValue);
	}
}